package main

import (
	"context"
	"crypto/ecdsa"
	"crypto/elliptic"
	"encoding/base64"
	"encoding/json"
	"google.golang.org/grpc"
	"log"
	"net"
	"xuefen_bank/crypt/curve"
	"xuefen_bank/crypt/recrypt"
	"xuefen_bank/grpc/proto/crypt"
	"xuefen_bank/utils"
)

const port = ":8888"

type server struct {
	crypt.ReCryptServer
}

var p256 = elliptic.P256()

// GenerateKeys
func (s *server) GenerateKeys(ctx context.Context, request *crypt.GenerateKeysRequest) (*crypt.GenerateKeysResponse, error) {
	log.Println("start method GenerateKeys success ")
	log.Printf("接收到来自客户端的消息, 说：%s \n", request.Name)
	// Alice Generate Alice key-pair
	aPriKey, aPubKey, _ := curve.GenerateKeys()
	aPriKeyPoint, _ := json.Marshal(&aPriKey)
	prikeyStr := utils.BytesToString(aPriKeyPoint)
	aPubKeyPoint, _ := json.Marshal(&aPubKey)
	pubkeyStr := utils.BytesToString(aPubKeyPoint)

	basePri := base64.StdEncoding.EncodeToString([]byte(prikeyStr))

	basePub := base64.StdEncoding.EncodeToString([]byte(pubkeyStr))
	log.Printf("服务端开始生成好了公私钥, 生成好的公私钥为：aPubKey = %s \n，aPriKey = %s \n", pubkeyStr, prikeyStr)
	log.Println("executes GenerateKeys success：")
	return &crypt.GenerateKeysResponse{
		Code:     200,
		APrivate: basePri,
		APublic:  basePub,
		Msg:      "success",
	}, nil
}

// cryptText 服务端必须实现的接口
func (s *server) CryptText(ctx context.Context, request *crypt.ACryptRequest) (*crypt.ACryptResponse, error) {
	log.Println("start method CryptText success ")
	aPublicKeyStr := request.APublicKey
	plainText := request.PlainText
	log.Println("aPublicKeyStr=======", aPublicKeyStr)
	log.Println("plainText=======", plainText)
	if aPublicKeyStr == "" || plainText == "" {
		return &crypt.ACryptResponse{Code: 500, CiphereText: nil, Msg: "数据为空！"}, nil
	}
	var aPublicKey *ecdsa.PublicKey
	if decodeString, err := base64.StdEncoding.DecodeString(aPublicKeyStr); err == nil {
		json.Unmarshal(decodeString, &aPublicKey)
	} else {
		return &crypt.ACryptResponse{Code: 500, CiphereText: nil, Msg: "解码错误！"}, nil
	}

	if aPublicKey.X == nil {
		return &crypt.ACryptResponse{Code: 500, CiphereText: nil, Msg: "加密错误！"}, nil
	}
	aPublicKey.Curve = p256
	cipherText, capsule, err := recrypt.Encrypt(plainText, aPublicKey)
	if err != nil {
		return &crypt.ACryptResponse{Code: 500, CiphereText: nil, Msg: "加密错误！"}, nil
	}

	cap, err := json.Marshal(&capsule)
	log.Println("executes CryptText success：cap={}", cap)
	return &crypt.ACryptResponse{
		Code:        200,
		CiphereText: cipherText,
		Capsule:     base64.StdEncoding.EncodeToString(cap),
		Msg:         "success",
	}, nil
}

// ReCrypt 服务端必须实现的接口
func (s *server) ReCrypt(ctx context.Context, request *crypt.ReCryptRequest) (*crypt.ReCryptResponse, error) {
	log.Println("start method ReCrypt success ")
	aPrivateStr := request.APrivate
	bPublicKeyStr := request.BPublicKey
	capsuleStr := request.Capsule
	if aPrivateStr == "" || bPublicKeyStr == "" || capsuleStr == "" {
		return &crypt.ReCryptResponse{Code: 500,
			NewCapsule: "",
			PubX:       "",
			Msg:        "数据不能为空！",
		}, nil
	}
	log.Println("capsuleStr==============================:", capsuleStr)
	var aPrivateKey *ecdsa.PrivateKey
	var bPublicKey *ecdsa.PublicKey
	var capsule *recrypt.Capsule
	if decodeString, err := base64.StdEncoding.DecodeString(aPrivateStr); err == nil {
		json.Unmarshal(decodeString, &aPrivateKey)
	} else {
		return &crypt.ReCryptResponse{Code: 500,
			NewCapsule: "",
			PubX:       "",
			Msg:        "解码错误！",
		}, nil
	}

	if decodeString, err := base64.StdEncoding.DecodeString(bPublicKeyStr); err == nil {
		json.Unmarshal(decodeString, &bPublicKey)
	} else {
		return &crypt.ReCryptResponse{Code: 500,
			NewCapsule: "",
			PubX:       "",
			Msg:        "解码错误！",
		}, nil
	}

	if decodeString, err := base64.StdEncoding.DecodeString(capsuleStr); err == nil {
		json.Unmarshal(decodeString, &capsule)
	} else {
		return &crypt.ReCryptResponse{Code: 500,
			NewCapsule: "",
			PubX:       "",
			Msg:        "解码错误！",
		}, nil
	}

	bPublicKey.Curve = p256
	capsule.E.Curve = p256
	capsule.V.Curve = p256
	log.Println("Alice generates re-encryption key")
	// Alice generates re-encryption key
	rk, pubX, err := recrypt.ReKeyGen(aPrivateKey, bPublicKey)
	if err != nil {
		log.Fatalf("%v", err)
		return &crypt.ReCryptResponse{Code: 500,
			NewCapsule: "",
			PubX:       "",
			Msg:        err.Error(),
		}, nil
	}
	log.Println("rk:", rk)
	marshal, _ := json.Marshal(capsule)
	log.Println("json后的capsule：", utils.BytesToString(marshal))
	// Server executes re-encrypt
	newCapsule, err := recrypt.ReEncryption(rk, capsule)

	if err != nil {
		log.Println(err.Error())
		return &crypt.ReCryptResponse{Code: 500,
			NewCapsule: "",
			PubX:       "",
			Msg:        err.Error(),
		}, nil
	}
	newCap, err := json.Marshal(&newCapsule)
	if err != nil {
		log.Fatalf("%v", err)
		return &crypt.ReCryptResponse{Code: 500,
			NewCapsule: "",
			PubX:       "",
			Msg:        err.Error(),
		}, nil
	}
	pubXByte, err := json.Marshal(&pubX)
	if err != nil {
		log.Fatalf("%v", err)
		return &crypt.ReCryptResponse{Code: 500,
			NewCapsule: "",
			PubX:       "",
			Msg:        err.Error(),
		}, nil
	}
	log.Println("executes re-encrypt success：")
	return &crypt.ReCryptResponse{
		Code:       200,
		NewCapsule: base64.StdEncoding.EncodeToString(newCap),
		PubX:       base64.StdEncoding.EncodeToString(pubXByte),
		Msg:        "success",
	}, nil
}

// DeCrypt 服务端必须实现的接口
func (s *server) DeCrypt(ctx context.Context, request *crypt.DeCryptRequest) (*crypt.DeCryptResponse, error) {
	log.Println("start method DeCrypt success ")
	newCapsuleStr := request.NewCapsule
	pubXStr := request.PubX
	bPrivateStr := request.BPrivate
	cipherText := request.CipherText

	if newCapsuleStr == "" || pubXStr == "" || bPrivateStr == "" || cipherText == nil {
		return &crypt.DeCryptResponse{
			Code:      500,
			PlainText: "",
			Msg:       "数据不能为空！",
		}, nil
	}
	var bPrivateKey *ecdsa.PrivateKey
	var publicKeyX *ecdsa.PublicKey
	var newCapsule *recrypt.Capsule
	if decodeString, err := base64.StdEncoding.DecodeString(bPrivateStr); err == nil {
		json.Unmarshal(decodeString, &bPrivateKey)
	} else {
		return &crypt.DeCryptResponse{
			Code:      500,
			PlainText: "",
			Msg:       err.Error(),
		}, nil
	}

	if decodeString, err := base64.StdEncoding.DecodeString(pubXStr); err == nil {
		json.Unmarshal(decodeString, &publicKeyX)
	} else {
		return &crypt.DeCryptResponse{
			Code:      500,
			PlainText: "",
			Msg:       err.Error(),
		}, nil
	}

	if decodeString, err := base64.StdEncoding.DecodeString(newCapsuleStr); err == nil {
		json.Unmarshal(decodeString, &newCapsule)
	} else {
		return &crypt.DeCryptResponse{
			Code:      500,
			PlainText: "",
			Msg:       err.Error(),
		}, nil
	}

	if bPrivateKey == nil || bPrivateKey.X == nil {
		return &crypt.DeCryptResponse{
			Code:      500,
			PlainText: "",
			Msg:       "上传的文件不对！",
		}, nil
	}
	bPrivateKey.PublicKey.Curve = p256
	publicKeyX.Curve = p256
	newCapsule.E.Curve = p256
	newCapsule.V.Curve = p256

	//  decrypts the cipherText
	plainText, err := recrypt.Decrypt(bPrivateKey, newCapsule, publicKeyX, cipherText)
	if err != nil {
		return &crypt.DeCryptResponse{
			Code:      500,
			PlainText: "",
			Msg:       err.Error(),
		}, nil
	}

	log.Println("PlainText by my B private key:", utils.BytesToString(plainText))
	log.Println(" run end method DeCrypt success ")
	return &crypt.DeCryptResponse{
		Code:      200,
		PlainText: utils.BytesToString(plainText),
		Msg:       "success！",
	}, nil
}

// DeCryptByOwnPri 服务端必须实现的接口
func (s *server) DeCryptByOwnPri(ctx context.Context, request *crypt.DeCryptOwnRequest) (*crypt.DeCryptOwnResponse, error) {

	capsuleStr := request.Capsule
	aPrivateStr := request.APrivate
	cipherText := request.CipherText

	if capsuleStr == "" || aPrivateStr == "" || cipherText == nil {
		return &crypt.DeCryptOwnResponse{
			Code:      500,
			PlainText: "",
			Msg:       "数据不能为空！",
		}, nil
	}

	var bPrivateKey *ecdsa.PrivateKey
	var capsule *recrypt.Capsule

	json.Unmarshal(utils.StrToByte(aPrivateStr), &bPrivateKey)
	json.Unmarshal(utils.StrToByte(capsuleStr), &capsule)

	bPrivateKey.PublicKey.Curve = p256
	capsule.E.Curve = p256
	capsule.V.Curve = p256

	plainTextByMyPri, err := recrypt.DecryptOnMyPriKey(bPrivateKey, capsule, cipherText)
	if err != nil {
		log.Printf("%v", err)
		return &crypt.DeCryptOwnResponse{
			Code:      500,
			PlainText: "",
			Msg:       err.Error(),
		}, nil
	}
	log.Println("PlainText by my own private key:", string(plainTextByMyPri))

	return &crypt.DeCryptOwnResponse{
		Code:      200,
		PlainText: utils.BytesToString(plainTextByMyPri),
		Msg:       "success",
	}, nil
}

func main() {

	lis, err := net.Listen("tcp", port)
	if err != nil {
		log.Fatalf("failed to listen:%v", err)
	}

	s := grpc.NewServer()
	//reflection.Register(s)  // 为了后续使用grpcurl测试
	crypt.RegisterReCryptServer(s, &server{})

	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve:%v", err)
	}
}
